package glemipsc.instructions;

import glemipsc.Address;
import glemipsc.Function;
import glemipsc.GLEMipsC;
import glemipsc.RelativeAddress;
import glemipsc.Type;
import glemipsc.implementations.Argument;

import java.io.Serializable;
import java.util.List;

public class Return extends BaseInstruction implements Serializable, Instruction, Expression {
	private Expression op = null;
	private Address addr;
	
	public Return() {
	}
	
	public Return(Expression op) {
		this.op = op;
	}
	
	public Expression getOperand(int index) {
		if (index == 0)
			return op;
		return null;
	}
	
	public int getNumberOfOperands() {
		return 1;
	}

	public int getSize() {
		return 0;
	}

	public Type getType() {
		return Type.createFromName("void");
	}

	public int getImmediateValue() {
		return 0;
	}

	public boolean isImmediate() {
		return false;
	}

	public Address getStoreAddress() {
		return addr;
	}

	public int getStoredSize() {
		// TODO Auto-generated method stub
		return 0;
	}

	public boolean isStored() {
		return true;
	}

	public void setStoreAddress(Address addr) {
		this.addr = addr;
	}

	public void computeInstruction(Argument result, List<glemipsc.implementations.Instruction> instructions, Function func) {
		glemipsc.implementations.Implementation impl = GLEMipsC.compiler.getEnvironment().implementation;
		//instructions.add(impl.getSub(impl.getStackPointerRegister(), impl.getStackPointerRegister(), impl.getImmediate(4), false));
		if (op != null)
			op.computeInstruction(result, instructions, func);
		instructions.add(impl.getSub(impl.getStackPointerRegister(), impl.getStackPointerRegister(), impl.getImmediate(1), false));
		instructions.add(impl.getLd(impl.getReturnRegister(), new RelativeAddress(impl.getStackPointerRegister(), 0), 4));
		if (op != null)
			instructions.add(impl.getSt(result, new RelativeAddress(impl.getStackPointerRegister(), 0), 4));
		instructions.add(impl.getJmp(impl.getReturnRegister()));
	}

}
